package com.ruoyi.quartz.controller

import com.ruoyi.common.annotation.Log
import com.ruoyi.common.constant.Constants
import com.ruoyi.common.core.controller.BaseController
import com.ruoyi.common.core.domain.AjaxResult
import com.ruoyi.common.core.page.TableDataInfo
import com.ruoyi.common.enums.BusinessType
import com.ruoyi.common.exception.job.TaskException
import com.ruoyi.common.utils.MyStringUtils
import com.ruoyi.common.utils.poi.ExcelUtil
import com.ruoyi.quartz.domain.SysJob
import com.ruoyi.quartz.service.ISysJobService
import com.ruoyi.quartz.util.CronUtils
import com.ruoyi.quartz.util.ScheduleUtils
import org.apache.commons.lang3.StringUtils
import org.quartz.SchedulerException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import javax.servlet.http.HttpServletResponse

/**
 * 调度任务信息操作处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/job")
open class SysJobController : BaseController() {
    @Autowired
    private lateinit var jobService: ISysJobService

    /**
     * 查询定时任务列表
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:list')")
    @GetMapping("/list")
    fun list(sysJob: SysJob?): TableDataInfo {
        startPage()
        val list = jobService.selectJobList(sysJob)
        return getDataTable(list)
    }

    /**
     * 导出定时任务列表
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:export')")
    @Log(title = "定时任务", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    fun export(response: HttpServletResponse, sysJob: SysJob) {
        val list = jobService.selectJobList(sysJob)
        val util = ExcelUtil(SysJob::class.java)
        util.exportExcel(response, list, "定时任务")
    }

    /**
     * 获取定时任务详细信息
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:query')")
    @GetMapping(value = ["/{jobId}"])
    fun getInfo(@PathVariable("jobId") jobId: Long?): AjaxResult {
        return success(jobService.selectJobById(jobId))
    }

    /**
     * 新增定时任务
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:add')")
    @Log(title = "定时任务", businessType = BusinessType.INSERT)
    @PostMapping
    @Throws(SchedulerException::class, TaskException::class)
    fun add(@RequestBody job: SysJob): AjaxResult {
        if (!CronUtils.isValid(job.cronExpression)) {
            return error("新增任务'" + job.jobName + "'失败，Cron表达式不正确")
        } else if (StringUtils.containsIgnoreCase(job.invokeTarget, Constants.LOOKUP_RMI)) {
            return error("新增任务'" + job.jobName + "'失败，目标字符串不允许'rmi'调用")
        } else if (MyStringUtils.myContainsAnyIgnoreCase(job.invokeTarget, *arrayOf(Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS))) {
            return error("新增任务'" + job.jobName + "'失败，目标字符串不允许'ldap(s)'调用")
        } else if (MyStringUtils.myContainsAnyIgnoreCase(job.invokeTarget, *arrayOf(Constants.HTTP, Constants.HTTPS))) {
            return error("新增任务'" + job.jobName + "'失败，目标字符串不允许'http(s)'调用")
        } else if (MyStringUtils.myContainsAnyIgnoreCase(job.invokeTarget, *Constants.JOB_ERROR_STR)) {
            return error("新增任务'" + job.jobName + "'失败，目标字符串存在违规")
        } else if (!ScheduleUtils.whiteList(job.invokeTarget)) {
            return error("新增任务'" + job.jobName + "'失败，目标字符串不在白名单内")
        }
        job.createBy = username
        return toAjax(jobService.insertJob(job))
    }

    /**
     * 修改定时任务
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
    @PutMapping
    @Throws(SchedulerException::class, TaskException::class)
    fun edit(@RequestBody job: SysJob): AjaxResult {
        if (!CronUtils.isValid(job.cronExpression)) {
            return error("修改任务'" + job.jobName + "'失败，Cron表达式不正确")
        } else if (StringUtils.containsIgnoreCase(job.invokeTarget, Constants.LOOKUP_RMI)) {
            return error("修改任务'" + job.jobName + "'失败，目标字符串不允许'rmi'调用")
        } else if (MyStringUtils.myContainsAnyIgnoreCase(job.invokeTarget, *arrayOf(Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS))) {
            return error("修改任务'" + job.jobName + "'失败，目标字符串不允许'ldap(s)'调用")
        } else if (MyStringUtils.myContainsAnyIgnoreCase(job.invokeTarget, *arrayOf(Constants.HTTP, Constants.HTTPS))) {
            return error("修改任务'" + job.jobName + "'失败，目标字符串不允许'http(s)'调用")
        } else if (MyStringUtils.myContainsAnyIgnoreCase(job.invokeTarget, *Constants.JOB_ERROR_STR)) {
            return error("修改任务'" + job.jobName + "'失败，目标字符串存在违规")
        } else if (!ScheduleUtils.whiteList(job.invokeTarget)) {
            return error("修改任务'" + job.jobName + "'失败，目标字符串不在白名单内")
        }
        job.updateBy = username
        return toAjax(jobService.updateJob(job))
    }

    /**
     * 定时任务状态修改
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    @Throws(SchedulerException::class)
    fun changeStatus(@RequestBody job: SysJob): AjaxResult {
        val newJob = jobService.selectJobById(job.jobId)
        newJob?.status = job.status
        return toAjax(jobService.changeStatus(newJob))
    }

    /**
     * 定时任务立即执行一次
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
    @Log(title = "定时任务", businessType = BusinessType.UPDATE)
    @PutMapping("/run")
    @Throws(SchedulerException::class)
    fun run(@RequestBody job: SysJob?): AjaxResult {
        val result = jobService.run(job)
        return if (result) success() else error("任务不存在或已过期！")
    }

    /**
     * 删除定时任务
     */
    @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
    @Log(title = "定时任务", businessType = BusinessType.DELETE)
    @DeleteMapping("/{jobIds}")
    @Throws(SchedulerException::class, TaskException::class)
    fun remove(@PathVariable jobIds: Array<Long>?): AjaxResult {
        jobService.deleteJobByIds(jobIds)
        return success()
    }
}
